﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;

namespace PPSkin
{
    public partial class PPTabButtonBar : UserControl
    {
        #region 动画属性
        private int selectRectX = 0;
        private int selectRectY = 0;
        private int selectRectW = 0;
        private int selectRectH = 0;

        private PPAnimation animation;

        [Browsable(false), Description("动画属性，不可手动修改")]
        public int SelectRectX
        { get { return selectRectX; } set { selectRectX = value; this.Invalidate(); } }

        [Browsable(false), Description("动画属性，不可手动修改")]
        public int SelectRectY
        { get { return selectRectY; } set { selectRectY = value; this.Invalidate(); } }

        [Browsable(false), Description("动画属性，不可手动修改")]
        public int SelectRectW
        { get { return selectRectW; } set { selectRectW = value; this.Invalidate(); } }

        [Browsable(false), Description("动画属性，不可手动修改")]
        public int SelectRectH
        { get { return selectRectH; } set { selectRectH = value; this.Invalidate(); } }
        #endregion

        #region 公共属性
        [Description("当前选中下标")]
        public int SelectIndex = 0;

        [Description("是否启用动画")]
        public bool EnableAnime { get; set; } = true;

        [Description("动画类型")]
        public AnimationType AnimationType { get; set; } = AnimationType.BounceOut;

        [Description("动画时间")]
        [Browsable(true)]
        public int AnimationTime { get; set; } = 500;

        [Description("选项按钮文本")]
        public List<string> Texts { get; set; } = new List<string> { "tabpage1", "tabpage2" };

        [Description("文本位移")]
        public Point TextOffset { get; set; } = new Point(0,0);

        [Description("文本对齐方式")]
        public StringAlignment TextAlignment { get; set; } = StringAlignment.Center;

        [Description("是否显示图片")]
        public bool ShowImages { get; set; } = false;

        [Description("图片列表")]
        public List<Bitmap> Images { get; set; } = new List<Bitmap>();

        [Description("图片大小")]
        public Size ImageSize { get; set; } = new Size(25, 25);

        [Description("图片位置")]
        public Point ImageOffset { get; set; } = new Point(0, 0);

        [Description("按钮的宽度，若为垂直排列时则为高度，ItemAutoSize为false时生效")]
        public int ButtonWidth { get; set; } = 100;

        [Description("启用自动宽度（高度）")]
        public bool ItemAutoSize { get; set; } = false;

        [Description("正常文字颜色")]
        public Color NormalForeColor { get; set; } = Color.Black;

        [Description("选中时文字颜色")]
        public Color SelectForeColor { get; set; } = Color.White;

        [Description("正常背景色")]
        public Color NormalBaseColor { get; set; } = Color.White;

        [Description("选中背景色")]
        public Color SelectBaseColor { get; set; } = Color.DimGray;

        [Description("选中条颜色")]
        public Color SelectBarColor { get; set; } = Color.DodgerBlue;

        [Description("鼠标选中背景色")]
        public Color MouseSelectColor { get; set; } = Color.Silver;

        [Description("选中条的高度，垂直排列时为宽度")]
        public int BarSize
        {
            get { return barSize; }
            set
            {
                if (value <= 0 || ((SelectBarPosition == selectBarPosition.Top || SelectBarPosition == selectBarPosition.Bottom) && value > this.Height) || ((SelectBarPosition == selectBarPosition.Left || SelectBarPosition == selectBarPosition.Right) && value > this.Width))
                    return;
                barSize = value;
            }
        }

        [Description("排列方向")]
        public direction Direction { get; set; } = direction.Horizontal;

        [Description("选中背景位置")]
        public selectBarPosition SelectBarPosition { get; set; } = selectBarPosition.Bottom;

        [Description("字符绘制方式")]
        public Enums.DrawMode TextDrawMode { get; set; } = Enums.DrawMode.Anti;

        [Description("绑定的TabControl控件")]
        public TabControl BindTabControl
        {
            get { return bindTabControl; }
            set
            {
                if (bindTabControl != null && !bindTabControl.IsDisposed)
                {
                    bindTabControl.SelectedIndexChanged -= TabControl_SelectedIndexChanged;
                    bindTabControl.ControlAdded -= TabControl_ControlChanged;
                    bindTabControl.ControlRemoved -= TabControl_ControlChanged;
                    bindTabControl.Disposed -= TabControl_Disposed;
                }

                bindTabControl = value;

                if (bindTabControl == null)
                {
                    Texts.Clear();
                    SelectItem(-1, false);
                    this.Invalidate();
                    return;
                }

                bindTabControl.SelectedIndexChanged += TabControl_SelectedIndexChanged;
                bindTabControl.ControlAdded += TabControl_ControlChanged;
                bindTabControl.ControlRemoved += TabControl_ControlChanged;
                bindTabControl.Disposed += TabControl_Disposed;

                List<string> texts = new List<string>();

                foreach (TabPage page in bindTabControl.TabPages)
                {
                    texts.Add(page.Text);
                }
                Texts = texts;
                if (Texts.Count > 0)
                {
                    SelectItem(0, false);
                }
                this.Invalidate();
            }
        }
        #endregion

        #region 私有属性
        /// <summary>
        /// 绑定的TabControl控件
        /// </summary>
        private TabControl bindTabControl;

        /// <summary>
        /// 选中条的高度，垂直排列时为宽度
        /// </summary>
        private int barSize = 10;

        /// <summary>
        /// 鼠标选中的下标
        /// </summary>
        private int MouseSelectIndex = -1;
        #endregion

        #region 枚举
        public enum direction
        {
            Vertical,
            Horizontal
        }

        public enum selectBarPosition
        {
            Left,
            Top,
            Right,
            Bottom
        }
        #endregion

        public PPTabButtonBar()
        {
            InitializeComponent();
            base.SetStyle(
            ControlStyles.UserPaint |
            ControlStyles.DoubleBuffer |
            ControlStyles.OptimizedDoubleBuffer |
            ControlStyles.AllPaintingInWmPaint |
            ControlStyles.ResizeRedraw |
            ControlStyles.SupportsTransparentBackColor, true);
            base.UpdateStyles();

            animation = new PPAnimation(this) { AnimationType = AnimationType,AnimationRunType=AnimationRunType.Interrupt };
        }

        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x02000000;//用双缓冲绘制窗口的所有子控件
                return cp;
            }
        }

        /// <summary>
        /// 绑定一个TabControl
        /// </summary>
        /// <param name="tabControl"></param>
        public void BindingTabControl(TabControl tabControl)
        {
            BindTabControl=tabControl;
        }

        private void TabControl_Disposed(object sender, EventArgs e)
        {
            if (bindTabControl != null)
            {
                bindTabControl.SelectedIndexChanged -= TabControl_SelectedIndexChanged;
                bindTabControl.ControlAdded -= TabControl_ControlChanged;
                bindTabControl.ControlRemoved -= TabControl_ControlChanged;
                bindTabControl.Disposed -= TabControl_Disposed;
                bindTabControl = null;
            }
        }

        private void TabControl_ControlChanged(object sender, ControlEventArgs e)
        {
            List<string> texts = new List<string>();
            foreach (TabPage page in (sender as TabControl).TabPages)
            {
                texts.Add(page.Text);
            }
            Texts = texts;
            this.Invalidate();
            SelectItem((sender as TabControl).SelectedIndex);
        }

        private void TabControl_SelectedIndexChanged(object sender, EventArgs e)
        {
            SelectItem((sender as TabControl).SelectedIndex);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            SelectItem(0, false);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (Texts.Count() == 0)
                return;

            Graphics g = e.Graphics;
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
            g.TextRenderingHint = TextDrawMode ==Enums.DrawMode.Anti ? System.Drawing.Text.TextRenderingHint.AntiAlias : System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

            g.Clear(NormalBaseColor);//先画背景色

            StringFormat stringFormat = new StringFormat();
            stringFormat.Alignment = TextAlignment;
            stringFormat.LineAlignment = StringAlignment.Center;
            stringFormat.FormatFlags = StringFormatFlags.NoClip;

            float itemWidth = ButtonWidth;

            if (ItemAutoSize)//自动宽度
            {
                if (Texts.Count() > 0)
                {
                    if (Direction == direction.Vertical)
                    {
                        itemWidth = (float)this.Height / Texts.Count();
                    }
                    else
                    {
                        itemWidth = (float)this.Width / Texts.Count();
                    }
                }
            }

            SolidBrush BrushText = new SolidBrush(NormalForeColor);
            SolidBrush BrushTextSel = new SolidBrush(SelectForeColor);
            SolidBrush BrushSelectBase = new SolidBrush(SelectBaseColor);
            SolidBrush BrushMouseSelectBase = new SolidBrush(MouseSelectColor);
            for (int i = 0; i < Texts.Count(); i++)
            {
                Rectangle rect = new Rectangle((int)(i * itemWidth), 0, (int)itemWidth, this.Height);
                if (Direction == direction.Vertical)
                {
                    rect = new Rectangle(0, (int)(i * itemWidth), this.Width, (int)itemWidth);
                }
                var textRect=new Rectangle(rect.X+TextOffset.X,rect.Y+TextOffset.Y, rect.Width, rect.Height);

                if (i == SelectIndex)
                {
                    g.FillRectangle(BrushSelectBase, rect);//画选中背景色
                    if (MouseSelectIndex == i)
                    {
                        g.FillRectangle(BrushMouseSelectBase, rect);//画选中背景色
                    }

                    g.DrawString(Texts[i], this.Font, BrushTextSel, textRect, stringFormat);
                }
                else
                {
                    if (MouseSelectIndex == i)
                    {
                        g.FillRectangle(BrushMouseSelectBase, rect);//画选中背景色
                    }
                    g.DrawString(Texts[i], this.Font, BrushText, textRect, stringFormat);
                }

                if (ShowImages)
                {
                    if (Images.Count - 1 >= i)
                    {
                        Image img = Images[i];
                        if (img != null)
                        {
                            g.DrawImage(img, new Rectangle(rect.Left + ImageOffset.X, rect.Top + ImageOffset.Y, ImageSize.Width, ImageSize.Height));
                        }
                    }
                }
            }

            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default;
            SolidBrush selectBarBrush = new SolidBrush(SelectBarColor);
            g.FillRectangle(selectBarBrush, new Rectangle(SelectRectX, SelectRectY, SelectRectW, SelectRectH));//画选中条背景色

            BrushText.Dispose();
            BrushTextSel.Dispose();
            BrushSelectBase.Dispose();
            BrushMouseSelectBase.Dispose();
            selectBarBrush.Dispose();
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
            int count = Texts.Count();
            if (count == 0)
                return;
            int x = e.X;
            int y = e.Y;
            int mouseIndex = -1;
            if (Direction == direction.Horizontal)
            {
                float itemWidth = ButtonWidth;
                if (ItemAutoSize)//自动宽度
                {
                    if (Texts.Count() > 0)
                    {
                        itemWidth = (float)this.Width / Texts.Count();
                    }
                }
                mouseIndex = (e.X / (int)itemWidth);
            }
            else
            {
                float itemWidth = ButtonWidth;
                if (ItemAutoSize)//自动宽度
                {
                    if (Texts.Count() > 0)
                    {
                        itemWidth = (float)this.Height / Texts.Count();
                    }
                }
                mouseIndex = (e.Y / (int)itemWidth);
            }

            bool changed = MouseSelectIndex == mouseIndex;

            if (mouseIndex >= 0 && mouseIndex < Texts.Count())
            {
                MouseSelectIndex = mouseIndex;
                this.Cursor = Cursors.Hand;
            }
            else
            {
                MouseSelectIndex = -1;
                this.Cursor = Cursors.Default;
            }

            if (changed)
            {
                this.Invalidate();
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            MouseSelectIndex = -1;
            this.Cursor = Cursors.Default;
            this.Invalidate();
        }

        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnMouseClick(e);

            int count = Texts.Count();
            if (count == 0)
                return;
            int x = e.X;
            int y = e.Y;
            if (Direction == direction.Horizontal)
            {
                float itemWidth = ButtonWidth;
                if (ItemAutoSize)//自动宽度
                {
                    if (Texts.Count() > 0)
                    {
                        itemWidth = (float)this.Width / Texts.Count();
                    }
                }
                int mouseIndex = (e.X / (int)itemWidth);
                if (mouseIndex > count - 1)
                    return;
                SelectItem(mouseIndex);
            }
            else
            {
                float itemWidth = ButtonWidth;
                if (ItemAutoSize)//自动宽度
                {
                    if (Texts.Count() > 0)
                    {
                        itemWidth = (float)this.Height / Texts.Count();
                    }
                }
                int mouseIndex = (e.Y / (int)itemWidth);
                if (mouseIndex > count - 1)
                    return;
                SelectItem(mouseIndex);
            }
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            SelectItem(this.SelectIndex, false);
        }

        public void SelectItem(int index, bool userAnim = true)
        {
            float itemWidth = ButtonWidth;
            if (ItemAutoSize)//自动宽度
            {
                if (Texts.Count() > 0)
                {
                    if (Direction == direction.Vertical)
                    {
                        itemWidth = (float)this.Height / Texts.Count();
                    }
                    else
                    {
                        itemWidth = (float)this.Width / Texts.Count();
                    }
                }
            }

            Rectangle rect = new Rectangle((int)(index * itemWidth), 0, (int)itemWidth, this.Height);
            if (Direction == direction.Vertical)
            {
                rect = new Rectangle(0, (int)(index * itemWidth), this.Width, (int)itemWidth);
            }

            switch (SelectBarPosition)
            {
                case selectBarPosition.Top: rect = new Rectangle(rect.Left, rect.Top, rect.Width, barSize); break;
                case selectBarPosition.Bottom: rect = new Rectangle(rect.Left, rect.Top + (rect.Height - barSize), rect.Width, barSize); break;
                case selectBarPosition.Left: rect = new Rectangle(rect.Left, rect.Top, barSize, (int)itemWidth); break;
                case selectBarPosition.Right: rect = new Rectangle(rect.Left + (rect.Width - barSize), rect.Top, barSize, (int)itemWidth); break;
            }

            if (userAnim && EnableAnime && !DesignMode)
            {
                Dictionary<string, float> dic = new Dictionary<string, float>();
                dic.Add("SelectRectX", rect.X);
                dic.Add("SelectRectY", rect.Y);
                dic.Add("SelectRectW", rect.Width);
                dic.Add("SelectRectH", rect.Height);

                animation.AnimationControl(dic, AnimationTime);
            }
            else
            {
                SelectRectX = rect.X;
                SelectRectY = rect.Y;
                SelectRectW = rect.Width;
                SelectRectH = rect.Height;
            }

            SelectIndex = index;
            if (SelectChanged != null)
            {
                SelectChanged(this, new SelectChangedArgs(index));
            }

            if (BindTabControl != null && !BindTabControl.IsDisposed)
            {
                BindTabControl.SelectedIndex = SelectIndex;
            }
        }

        [Description("选项改变事件")]
        public event EventHandler<SelectChangedArgs> SelectChanged;
    }

    public class SelectChangedArgs : EventArgs
    {
        public SelectChangedArgs(int index)
        {
            SelectIndex = index;
        }

        public int SelectIndex;
    }
}